//////////////////   碰 、杠 、胡 请求  //////////////////
import { retry } from 'rxjs';
import {checkHu}  from './checkHu';
import {resp}  from '../socket/message.utils';
import {adminTest}  from './cmmj.service';
import { defaultConfig } from '@game/config/config';
export async function peng(game, userId, cmmjService,moveToNextUser) {
  let seatData = game.gameSeats.find((item) => item.userId == userId);
  if (seatData == null) {
    console.log("can't find user game data.");
    return false;
  }
  //如果是他出的牌，则忽略
  if (game.turn == seatData.seatIndex) {
    console.log("it's your turn.");
    return false;
  }

  //如果没有碰的机会，则不能再碰
  if (seatData.canPeng == false) {
    console.log('seatData.peng == false');
    return false;
  }

  //和的了，就不要再来了
  if (seatData.hued) {
    console.log('you have already hued. no kidding plz.');
    return false;
  }

  //如果有人可以胡牌，则需要等待 至于要这样恶心的循环写么
  let i = game.turn;
  while (true) {
    i = (i + 1) % game.gameSeats.length;
    if (i == game.turn) {
      break;
    } else {
      let ddd = game.gameSeats[i];
      if (ddd.canHu && i != seatData.seatIndex) {
        return false;
      }
    }
  }

  let pai = game.chuPai;
  //验证手上的牌的数目
  let c = seatData.countMap[pai];
  if (c == null || c < 2) {
    console.log('pai:' + pai + ',count:' + c);
    console.log(seatData.holds);
    console.log('lack of mj.');
    return false;
  }
  clearAllOptions(game);
  
  delete game.guoshoupeng[userId]; //移除过手碰限制
  await cmmjService.redisService.hset({
    key: 'game' + game.roomId,
    value: { ...game },
    expire: defaultConfig.scoreCacheTime, // 3秒  为了就是瞬时刷新过快 导致的mysql问题
  });
  //进行碰牌处理
  //扣掉手上的牌
  //从此人牌中扣除
  for (let i = 0; i < 2; ++i) {
    let index = seatData.holds.indexOf(pai);
    if (index == -1) {
      console.log("can't find mj.");
      return false;
    }
    seatData.holds.splice(index, 1);
    seatData.countMap[pai]--;
  }
  seatData.penggangs.push(['peng', pai]);
  game.chuPai = -1;

  //广播通知其它玩家  对应的玩家更新数据
  await cmmjService.gateway.broadcastInRoom({
    seats: game.gameSeats,
    roomId: game.roomId,
    userId: seatData.userId,
    message: { userId: seatData.userId, pai: pai },
    type: resp.peng_notify,
    includSender: true,
  });

   //广播通知玩家出牌方
   seatData.canChuPai = true;
  //碰的玩家打牌
 await moveToNextUser(game, seatData.seatIndex);

 
 await cmmjService.gateway.broadcastInRoom({
    seats: game.gameSeats,
    roomId: game.roomId,
    userId: seatData.userId,
    message: seatData.userId,
    type: resp.game_chupai,
    includSender: true,
  });
  return true
}

export async function gang(game, userId, pai,buzhang, cmmjService,moveToNextUser,doUserMoPai) {
  let seatData = game.gameSeats.find((item) => item.userId == userId);
  if (seatData == null) {
    console.log("can't find user game data.");
    return false
  }
  let seatIndex = seatData.seatIndex;

  //如果没有杠的机会，则不能再杠
  if (seatData.canGang == false) {
    console.log('seatData.gang == false');
    return false
  }

  //和的了，就不要再来了
  if (seatData.hued) {
    console.log('you have already hued. no kidding plz.');
    return false;
  }

  if (!seatData.gangPai.includes(Number(pai))) {
    console.log("the given pai can't be ganged.");
    return false;
  }

  for (let index = 0; index <  game.gameSeats.length; index++) {
    const element =  game.gameSeats[index];
    if ((element.isQishou ) == true) {
      console.log('no need gang.');
      return false;
    }
  }

  //如果有人可以胡牌，则需要等待
  let i = game.turn;
  while (true) {
    i = (i + 1) % game.gameSeats.length;
    if (i == game.turn) {
      break;
    } else {
      let ddd = game.gameSeats[i];
      if (ddd.canHu && i != seatData.seatIndex) {
        return false;
      }
    }
  }
  delete game.guoshoupeng[userId]; //移除过手碰

  let numOfCnt = seatData.countMap[pai];

  let gangtype = '';
  //弯杠 去掉碰牌
  if (numOfCnt == 1) {
    gangtype = 'wangang';
  } else if (numOfCnt == 3) {
    gangtype = 'diangang';
  } else if (numOfCnt == 4) {
    gangtype = 'angang';
  } else {
    console.log('invalid pai count.');
    return false;
  }

  game.chuPai = -1;
  clearAllOptions(game);
  seatData.canChuPai = false;
  seatData.buzhang = buzhang;

  await cmmjService.gateway.broadcastInRoom({
    seats: game.gameSeats,
    roomId: game.roomId,
    userId: seatData.userId,
    message: { userId: seatData.userId, pai: pai, gangtype: gangtype },
    type: resp.hangang_notify,
    includSender: true,
  });
  //如果是弯杠，则需要检查是否可以抢杠
  let turnSeat = game.gameSeats[game.turn];
  if (numOfCnt == 1) {
    let canQiangGang =await checkCanQiangGang(game, turnSeat, seatData, pai,cmmjService);
    if (canQiangGang) {
      return false;
    }
  }

 return  doGang(game, turnSeat, seatData, gangtype, numOfCnt, pai, cmmjService,moveToNextUser,doUserMoPai);
}

export async function doGang(
  game,
  turnSeat,
  seatData,
  gangtype,
  numOfCnt,
  pai,
  cmmjService,
  moveToNextUser,doUserMoPai
) {
  let seatIndex = seatData.seatIndex;
  let gameTurn = turnSeat.seatIndex;

  let isZhuanShouGang = false;
  if (gangtype == 'wangang') {
    for (let i = 0; i < seatData.penggangs.length; i++) {
      if (
        seatData.penggangs[i][0] == 'peng' &&
        seatData.penggangs[i][1] == pai
      ) {
        seatData.penggangs[i][0] = 'wangang';
        break;
      }
    }
    //如果最后一张牌不是杠的牌，则认为是转手杠
    if (seatData.holds[seatData.holds.length - 1] != pai) {
      isZhuanShouGang = true;
    }
  }

  //记录下玩家的杠牌
  if (gangtype == 'angang') {
    seatData.penggangs.push(['angang', pai]);
    recordUserAction(game, seatData, 'angang');
  } else if (gangtype == 'diangang') {
    seatData.penggangs.push(['diangang', pai]);
    recordUserAction(game, seatData, 'diangang', gameTurn);
    let fs = turnSeat;
    recordUserAction(game, fs, 'fanggang', seatIndex);
  } else if (gangtype == 'wangang') {
    if (isZhuanShouGang == false) {
      recordUserAction(game, seatData, 'wangang');
    } else {
      recordUserAction(game, seatData, 'zhuanshougang');
    }
  }
  //进行碰牌处理
  //扣掉手上的牌
  //从此人牌中扣除
  for (let i = 0; i < numOfCnt; ++i) {
    let index = seatData.holds.indexOf(pai);
    if (index == -1) {
      console.log(seatData.holds);
      console.log("can't find mj.");
      return false;
    }
    seatData.holds.splice(index, 1);
    seatData.countMap[pai]--;
  }

  await checkTingPai(game, seatData,cmmjService);
  //通知其他玩家，有人杠了牌

  await cmmjService.gateway.broadcastInRoom({
    seats: game.gameSeats,
    roomId: game.roomId,
    userId: seatData.userId,
    message: { userId: seatData.userId, pai: pai, gangtype: gangtype },
    type: resp.gang_notify,
    includSender: true,
  });
  //只能放在这里。因为过手就会清除杠牌标记
  seatData.lastFangGangSeat = gameTurn;
  //变成自己的轮子
  await moveToNextUser(game, seatIndex);
  
  //再次摸牌
  await doUserMoPai(game, true);

 
  return true

}

export async function dochi(game, userId,index, cmmjService,moveToNextUser) {
 
  let seatData = game.gameSeats.find((item) => item.userId == userId);
  if (seatData == null) {
    console.log("can't find user game data.");
    return false;
  }
  //如果是他出的牌，则忽略
  if (game.turn == seatData.seatIndex) {
    console.log("it's your turn.");
    return false;
  }

  //防止数据被篡改，一切以服务器计算结果为准
  if (seatData.canChi == false) {
    console.log('seatData.canChi == false');
    return false;
  }
  for (let index = 0; index <  game.gameSeats.length; index++) {
    const element =  game.gameSeats[index];
    if ((element.canGang || element.canPeng || element.canHu ||element.isQishou ) == true) {
      console.log('no need chi.');
      return false;
    }
  }
 
  //和的了，就不要再来了
  if (seatData.hued) {
    console.log('you have already hued. no kidding plz.');
    return false;
  }

  //如果有人可以胡牌，则需要等待 至于要这样恶心的循环写么
  let i = game.turn;
  while (true) {
    i = (i + 1) % game.gameSeats.length;
    if (i == game.turn) {
      break;
    } else {
      let ddd = game.gameSeats[i];
      if (ddd.canHu && i != seatData.seatIndex) {
        return false;
      }
      if (ddd.canPeng && i != seatData.seatIndex) {
        return false;
      }
      if (ddd.canGang && i != seatData.seatIndex) {
        return false;
      }
    }
  }
  // 机器吃 
  if(index==undefined){
    index =Math.floor(Math.random()*seatData.chiPai.length)
  }
  let temp = seatData.chiPai[Number(index)];
  for (let i = 0; i < temp.length; ++i) {
    let mj = seatData.holds.indexOf(temp[i]);
    if (mj == -1 ||seatData.pai ==mj) {
      console.log("can't find mj.");
      continue;
    }
    seatData.holds.splice(mj, 1);
    seatData.countMap[temp[i]]--;
  }
  seatData.chi.push(temp);
  seatData.chiPai=[]
  game.chuPai = -1;

   //广播通知其它玩家  对应的玩家更新数据
   await cmmjService.gateway.broadcastInRoom({
    seats: game.gameSeats,
    roomId: game.roomId,
    userId: seatData.userId,
    message: { userId: seatData.userId, pais: temp,pai:seatData.pai },
    type: resp.chi_notify,
    includSender: true,
  });

  clearAllOptions(game);

  //广播通知玩家出牌方
  seatData.canChuPai = true;
  //吃成的玩家打牌
  await moveToNextUser(game, seatData.seatIndex);

  await cmmjService.gateway.broadcastInRoom({
     seats: game.gameSeats,
     roomId: game.roomId,
     userId: seatData.userId,
     message: seatData.userId,
     type: resp.game_chupai,
     includSender: true,
   });
   return true

}
export async function hu(game, userId,agpai, cmmjService,doGameOver) {
  let result =true

  for (let index = 0; index < game.gameSeats.length; index++) {
    const element = game.gameSeats[index];
   let result1 = await singlehu(game,element.userId,agpai,cmmjService,doGameOver)
   if(!result1){
    result =result1
   }
  }

  return result
}

export async function singlehu(game, userId,agpai, cmmjService,doGameOver) {
  
  let seatData = game.gameSeats.find((item) => item.userId == userId);
  
  if (seatData == null) {
    console.log("can't find user game data.");
    return false;
  }

  let seatIndex = seatData.seatIndex;

  //如果他不能和牌，那和个啥啊
  if(seatData.canHu == false && seatData.canGangHu == false){
    console.log("invalid request.");
    return false;
  }
  // hu的是当前轮次的杠说明是ming的
  let turnSeat = game.gameSeats[game.turn];
  seatData.isGangHu = turnSeat.lastFangGangSeat >= 0;
  //和的了，就不要再来了
  // if (seatData.hued &&!seatData.isGangHu) {
  //   console.log('you have already hued. no kidding plz.');
  //   return false;
  // }
  let numOfMJ = game.mahjongs.length - game.currentIndex;
  let leng =2-numOfMJ>0?numOfMJ:2

  if( game.round && game.round.length>0){

  }else{
    if(leng==2){
      let pai1 = game.mahjongs[game.currentIndex];
      game.currentIndex++;
      let pai2 = game.mahjongs[game.currentIndex];
      game.currentIndex++;
      const rank1 = Math.floor(pai1 % 9);
      const rank2 = Math.floor(pai2 % 9);
       game.round =  [(seatData.seatIndex+rank1-1)%4,(seatData.seatIndex+rank2-1)%4]
       game.zhongma=[pai1,pai2]
    }else if(leng==1){
      let pai = game.mahjongs[game.currentIndex];
      game.currentIndex++;
      const rank1 = Math.floor(pai % 9);
      game.round =  [(seatData.seatIndex+rank1-1)%4]
      game.zhongma=[pai]
  
    }else{
      game.round=[]
    }
  }
  
  //标记为和牌
  seatData.hued = true;
  let hupai = game.chuPai;
  let isZimo = false;

  let notify = -1;
  let type = '';
  let  ac:any=null;
  if (game.qiangGangContext != null) {
    let gangSeat = game.qiangGangContext.seatData;
    hupai = game.qiangGangContext.pai;
    notify = hupai;
    ac= recordUserAction(
      game,
      seatData,
      'qiangganghu',
      gangSeat.seatIndex,
    );
    ac.iszimo = false;
    type = 'qiangganghu';
    seatData.isQiangGangHu = true;
    game.qiangGangContext.isValid = false;
    game.yipaoduoxiang++;

    for (let i = 0; i < seatData.tingMap.length; i++) {
      if (seatData.tingMap[i][1].includes(hupai)) {
        recordUserAction(game,seatData,seatData.tingMap[i][0], gangSeat.seatIndex)
      }
    }
    // let idx = gangSeat.holds.indexOf(hupai);
    // if( idx != -1 ) {
    // 	gangSeat.holds.splice(idx,1);
    // 	gangSeat.countMap[hupai]--;
    // 	clientMgr.sendMsg(gangSeat.userId,'game_holds_push',gangSeat.holds);
    // }
    //将牌添加到玩家的手牌列表，供前端显示
    seatData.holds.push(hupai);
    if (seatData.countMap[hupai]) {
      seatData.countMap[hupai]++;
    } else {
      seatData.countMap[hupai] = 1;
    }
    // recordUserAction(game, gangSeat, 'beiqianggang', seatIndex);
    recordUserAction(game, seatData, 'beiqianggang', gangSeat.seatIndex);

  } else if (game.chuPai == -1) {
    hupai = seatData.holds[seatData.holds.length - 1];
    notify = -1;
    // 这里区分 补和杠
    if (seatData.isGangHu ) {
      if(agpai){
        if (turnSeat.lastFangGangSeat == seatIndex) {
          ac = recordUserAction(game, seatData, 'ganghua');
            type = 'ganghua';
            ac.iszimo = true;
            for (let i = 0; i < seatData.tingMap.length; i++) {
              if (seatData.tingMap[i][1].includes(agpai)) {
                recordUserAction(game,seatData,seatData.tingMap[i][0])
              }
            }
        } else {
          ac = recordUserAction(
            game,
            seatData,
            'dianganghua',
            turnSeat.lastFangGangSeat,
          );
          type = 'dianganghua';
          ac.iszimo = false;
          for (let i = 0; i < seatData.tingMap.length; i++) {
            if (seatData.tingMap[i][1].includes(agpai)) {
              recordUserAction(game,seatData,seatData.tingMap[i][0], turnSeat.lastFangGangSeat)
            }
          }
         
        }
      }else{
        // buzhang
        let flag=true;
        for (let i = 0; i < seatData.tingMap.length; i++) {
          if (seatData.tingMap[i][1].includes(hupai)&&seatData.tingMap[i][0]!="normal") {
            recordUserAction(game,seatData,seatData.tingMap[i][0])
            type =seatData.tingMap[i][0];
            flag=false
          }
        }
        if(flag){
          ac = recordUserAction(game, seatData, 'zimo');
          type = 'zimo';
          ac.iszimo = true;
        }
      }
      
    } else {
      // 计算是不是dahu  //排除normal
      let flag=true;
      for (let i = 0; i < seatData.tingMap.length; i++) {
        if (seatData.tingMap[i][1].includes(hupai)&&seatData.tingMap[i][0]!="normal") {
          recordUserAction(game,seatData,seatData.tingMap[i][0])
          type = seatData.tingMap[i][0];
          flag=false
        }
      }
      if(flag){
        ac = recordUserAction(game, seatData, 'zimo');
        type = 'zimo';
        ac.iszimo = true;
      }
    }
    isZimo = true;
    seatData.numZiMo++;
  } else {
    notify = game.chuPai;
    //将牌添加到玩家的手牌列表，供前端显示
    seatData.holds.push(game.chuPai);
    if (seatData.countMap[game.chuPai]) {
      seatData.countMap[game.chuPai]++;
    } else {
      seatData.countMap[game.chuPai] = 1;
    }
    game.yipaoduoxiang++;
   

    // //炮胡 排除补涨的
    // if (turnSeat.lastFangGangSeat >= 0 && !turnSeat.buzhang) {
    //   at = 'gangpaohu';
    // }
    let flag=true;
    for (let i = 0; i < seatData.tingMap.length; i++) {
      if (seatData.tingMap[i][1].includes(notify)&&seatData.tingMap[i][0]!="normal") {
        recordUserAction(game,seatData,seatData.tingMap[i][0],game.turn)
        type =seatData.tingMap[i][0];
        flag=false
      }
    }
    if(flag){
      ac = recordUserAction(game, seatData, "hu", game.turn);
      type ="hu"
      ac.iszimo = false;
    }
   
    
    //记录玩家放炮信息
    let fs = game.gameSeats[game.turn];
    fs.numJiePao++;
    recordUserAction(game, fs, 'fangpao', seatIndex);
    game.fangpaoshumu++;
  }
  
  game.firstHupai = seatIndex;
  seatData.iszimo = isZimo;
  //如果是最后一张牌，则认为是海底胡
  seatData.isHaiDiHu = game.currentIndex == game.mahjongs.length;  

  if (game.chupaiCnt == 0 && game.button == seatData.seatIndex) {
    seatData.isTianHu = true;
  }
  if (
    game.chupaiCnt == 1 &&
    game.turn == game.button &&
    game.button != seatData.seatIndex
  ) {
    seatData.isDiHu = true;
  }

  // if(agpai==-1){
  // }
  clearAllOptions(game, seatData);

  //如果还有人可以胡牌，则等待
  // for (let i = 0; i < game.gameSeats.length; ++i) {
  //   let ddd = game.gameSeats[i];
  //   if (ddd.canHu) {
  //     return false;
  //   }
  // }
  await doGameOver(game, seatData.userId,false,type,notify,isZimo);
}

export async function guo(game, userId, cmmjService,moveToNextUser,doUserMoPai,loopgang) {
  let seatData = game.gameSeats.find((item) => item.userId == userId);
  if (seatData == null) {
    console.log("can't find user game data.");
    return false;
  }
  let seatIndex = seatData.seatIndex;

  
  //如果是玩家自己的轮子，不是接牌，则不需要额外操作
  let doNothing = game.chuPai == -1 && game.turn == seatIndex;
  
  if (game.chuPai != -1) {
    if (game.guoshoupeng[userId] == null) game.guoshoupeng[userId] = {};
    game.guoshoupeng[userId][game.chuPai] = 1;
  }
  //这里还要处理过胡的情况
  if (game.chuPai >= 0 && seatData.canHu) {
    seatData.guoHuTime++;
   
  }
  clearAllOptions(game, seatData);

  for (let index = 0; index <  game.gameSeats.length; index++) {
    const element =  game.gameSeats[index];
    if ((element.canGang || element.canPeng || element.canHu ||element.isQishou || seatData.canChi) == true) {
      console.log('no need guo.',element);
      return false;
    }
  }
  await cmmjService.redisService.hset({
    key: 'game' + game.roomId,
    value: { ...game },
    expire: defaultConfig.scoreCacheTime, // 3秒  为了就是瞬时刷新过快 导致的mysql问题
  });
  if (doNothing) {
      //清除所有的操作
      await moveToNextUser(game, seatIndex);

      return false;
  }

  //如果还有人可以操作，则等待
  for (let i = 0; i < game.gameSeats.length; ++i) {
    let ddd = game.gameSeats[i];
    if (hasOperations(ddd)) {
      return false;
    }
  }

  //如果是已打出的牌，则需要通知。
  if (game.chuPai >= 0) {
    let uid = game.gameSeats[game.turn].userId;
    cmmjService.gateway.broadcastInRoom({
      seats: game.gameSeats,
      roomId: game.roomId,
      userId: seatData.userId,
      message: { userId: uid, pai: game.chuPai },
      type: resp.guo_notify,
      includSender: true,
    });

    seatData.folds.push(game.chuPai);
    game.chuPai = -1;
  }

  let qiangGangContext = game.qiangGangContext;
  clearAllOptions(game, seatData);
  await cmmjService.redisService.hset({
    key: 'game' + game.roomId,
    value: { ...game },
    expire: defaultConfig.scoreCacheTime, // 3秒  为了就是瞬时刷新过快 导致的mysql问题
  });

  console.log('过了后判断轮次摸牌');
  if (qiangGangContext != null && qiangGangContext.isValid) {
    console.log('不抢杠接着开杠');
    doGang(
      game,
      qiangGangContext.turnSeat,
      qiangGangContext.seatData,
      'wangang',
      1,
      qiangGangContext.pai,
      cmmjService,
      moveToNextUser,doUserMoPai
    );
  } else {
    //下家摸牌
    for (let index = 0; index < game.gameSeats.length; index++) {
      const element = game.gameSeats[index];
     if(element.canHu){
        return
      }
    }

  if(game.gangkai.length>0){
    for (let index = 0; index < game.gangkai.length; index++) {
      loopgang(game, game.gangkai[index]);
    }
    game.gangkai =[]
    await cmmjService.redisService.hset({
      key: 'game' + game.roomId,
      value: { ...game },
      expire: defaultConfig.scoreCacheTime, // 3秒  为了就是瞬时刷新过快 导致的mysql问题
    });
  }else if(game.gangkai.length==0){
      // // 所有人都没action的时候才是执行这个
      // 说明所有的都放弃了这次ganghu  可以把状态重置
      for (let index = 0; index < game.gameSeats.length; index++) {
        const element = game.gameSeats[index];
        element.canGangHu=false
      }
      game.gangpao=[]
      await  moveToNextUser(game);
      await  doUserMoPai(game);
   }
   return true


  }
}

export async function checkTingPai(game: any, seatData: any,cmmjService) {
  //检测特殊番数
  let dahuCount=0;
  seatData.tingMap=[]
  seatData.pattern=""

  //过滤条件 "{"qidui":1,"haoqidui":1,"jiangjianghu":1,"pengpenghu":1,"quanqiuren":1,"qingyise":1}"
  let isDaHu_BBH=JSON.parse(game.isDaHu)


  // 不能排序手牌哦
  let holds =seatData.holds.slice(0)
  if(game.isCsJiang){
    let is7duiHu: any = checkHu.check7dui(holds, game.laizi);
    // 7对
    if (is7duiHu.length > 0 && isDaHu_BBH.qidui==1) {
      console.log('7对可听:', checkHu.getName(is7duiHu));  
      let is7duiHu2 = checkHu.checkSuper7dui(holds, game.laizi);
      if (is7duiHu2.length > 0  && isDaHu_BBH.haoqidui==1) {
        seatData.tingMap = seatData.tingMap.concat([["hao7dui",is7duiHu]]);
        seatData.pattern += 'hao7dui,';
        dahuCount+=2;
        console.log('豪7子:', checkHu.getName(is7duiHu));
      } else {
        seatData.tingMap = seatData.tingMap.concat([["7dui",is7duiHu]]);
        seatData.pattern += '7dui,';
      
        dahuCount+=1;
      }
    }
    // 将将胡
    let isJiangHu: any = checkHu.checkJiangJiang(holds, game.laizi,seatData);
    if (isJiangHu.length > 0  && isDaHu_BBH.jiangjianghu==1) {
      console.log(
        '需要判断没吃，碰杠都是将，将将胡:',
        checkHu.getName(isJiangHu),
      );

      seatData.tingMap = seatData.tingMap.concat([["JiangHu",isJiangHu]]);

      seatData.pattern += 'JiangHu,';
    
      dahuCount+=1;

    }
    // 碰碰胡 可以不需要将
    let isPengHu: any = checkHu.checkPengPeng(holds, game.laizi,seatData);
    if (isPengHu.length > 0  && isDaHu_BBH.pengpenghu==1) {
      console.log('需要判断没吃，都是碰杠，碰碰胡:', checkHu.getName(isPengHu));

      seatData.tingMap = seatData.tingMap.concat([["PengHu",isPengHu]]);
      seatData.pattern += 'PengHu,';
      
      dahuCount+=1;

    }
    // quanqiuren
    let isQuanQiuRen: any = checkHu.checkQuanQiuRen(holds, game.laizi);
    if (isQuanQiuRen.length > 0  && isDaHu_BBH.quanqiuren==1 ) {
      console.log('需要判断只剩一张:', checkHu.getName(isQuanQiuRen));
      seatData.tingMap = seatData.tingMap.concat([["QuanQiuRen",isQuanQiuRen]]);

      seatData.pattern += 'QuanQiuRen,';
     
      dahuCount+=1;

    }
    // qingyise
    let isQingYiSe: any = checkHu.checkQingYiSe(holds, game.laizi,seatData);
    if (isQingYiSe.length > 0  && isDaHu_BBH.qingyise==1 ) {
      console.log('需要判断花色，清一色:', checkHu.getName(isQingYiSe));
      seatData.tingMap = seatData.tingMap.concat([["QingYiSe",isQingYiSe]]);

      seatData.pattern += 'QingYiSe,';
      
      dahuCount+=1;
    }
  }
  let isHu: any = checkHu.doCheckTing(holds, game.laizi,game.isCsJiang); //检查平胡

  if (dahuCount==0 &&isHu.length > 0) {
    console.log('可胡:', checkHu.getName(isHu));
    seatData.tingMap = seatData.tingMap.concat([["normal",isHu]]);

    seatData.pattern += 'normal';
    await  cmmjService.gateway.send({
      ...seatData,
      roomId: game.roomId,
      type: resp.game_ting,
      message: { tingMap: seatData.tingMap, pattern: seatData.pattern },
    });
  }else{
    if(dahuCount>0){
      if(seatData.pattern.length>0){
        seatData.pattern =seatData.pattern.substring(0,seatData.pattern.length-1);
      }
      await   cmmjService.gateway.send({
        ...seatData,
        roomId: game.roomId,
        type: resp.game_ting,
        message: { tingMap: seatData.tingMap, pattern: seatData.pattern },
      });
    }
   
  }
 
  
}


export async function clearAllOptions(game,seatData=null){
	let fnClear = function(sd){
        sd.canChi = false;
        sd.chiPai = [];
		sd.canPeng = false;
		sd.canGang = false;
		sd.gangPai = [];
		sd.canHu = false;
		sd.lastFangGangSeat = -1;	
	}
	if(seatData){
		fnClear(seatData);
	}
	else{
		game.qiangGangContext = null;
		for(let i = 0; i < game.gameSeats.length; ++i){
			fnClear(game.gameSeats[i]);
		}
	}
}

export async function recordUserAction(game,seatData,type,target=null){
  let d = {type:type,targets:[]};
  if(target != null){
    if(typeof(target) == 'number'){
      d.targets.push(target);	
    }
    else{
      d.targets = target;
    }
  }
  else{
    for(let i = 0; i < game.gameSeats.length; ++i){
      let s = game.gameSeats[i];
      if(i != seatData.seatIndex && s.hued == false){
        d.targets.push(i);
      }
    }		
  }
  seatData.actions.push(d);
  return d;
}

export async function checkCanQiangGang(game,turnSeat,seatData,pai,cmmjService){
  let hasActions = false;
  for(let i = 0; i < game.gameSeats.length; ++i){
      //杠牌者不检查
      if(seatData.seatIndex == i){
          continue;
      }
      let ddd = game.gameSeats[i];
      //已经和牌的不再检查
      if(ddd.hued){
          continue;
      }

     await checkCanHu(game,ddd,pai);
      if(ddd.canHu){
      await  sendOperations(game,ddd,pai,cmmjService);
          hasActions = true;
      }
  }
  if(hasActions){
      game.qiangGangContext = {
          turnSeat:turnSeat,
          seatData:seatData,
          pai:pai,
          isValid:true,
      }
  }
  else{
      game.qiangGangContext = null;
  }
  
  return game.qiangGangContext != null;
}


export  function  hasOperations(seatData) {
  if (seatData.canGang || seatData.canPeng || seatData.canHu) {
    return true;
  }
  return false;
}

export  function checkCanHu(game, seatData, targetPai) {
  //game.lastHuPaiSeat = -1;
  seatData.canHu = false;

  let count = 0;
  for (let i = 0; i < game.laizi.length; i++) {
    //鬼牌大于等于4，直接胡牌
    count += seatData.countMap[game.laizi[i]];
  }
  if (count > 3) {
    seatData.canHu = true;
  }
  // 累计计算
  for (let i = 0; i < seatData.tingMap.length; i++) {
    if (seatData.tingMap[i].includes(targetPai)) {

      seatData.canHu = true;
      break;
    }
  }
}
export async function sendOperations(game, seatData, pai,cmmjService) {
  if (hasOperations(seatData)) {
    //保存游戏  socket消息过快 缓存数据没更新到 导致有动作但是状态不对
    await cmmjService.redisService.hset({
      key: 'game' + game.roomId,
      value: { ...game },
      expire: defaultConfig.scoreCacheTime, // 3秒  为了就是瞬时刷新过快 导致的mysql问题
    });
    if (pai == -1) {
      //起手
      pai = seatData.holds[seatData.holds.length - 1];
    }

  
    if (seatData.canHu) {
      let data: any = { pai: pai };
      data.hu = true;
      //如果可以有操作，则进行操作
      await cmmjService.gateway.send({
        ...seatData,
        roomId: game.roomId,
        message: data,
        type: resp.game_action,
      });
    }
    if (seatData.canGang) {
      let data: any = { pai: pai };
      data.gang = true;
      data.gangpai = seatData.gangPai;
      //如果可以有操作，则进行操作
      await cmmjService.gateway.send({
        ...seatData,
        roomId: game.roomId,
        message: data,
        type: resp.game_action,
      });
    }
    if (seatData.canPeng) {
      let data: any = { pai: pai };
      data.peng = true;
      await cmmjService.gateway.send({
        ...seatData,
        roomId: game.roomId,
        message: data,
        type: resp.game_action,
      });
    }
  } 
}

